package com.wnzt.baszh.ca;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.security.MessageDigest;

import net.netca.pki.Certificate;
import net.netca.pki.Device;
import net.netca.pki.DeviceSet;
import net.netca.pki.KeyPair;
import net.netca.pki.PkiException;
import net.netca.pki.Signature;
import net.netca.pki.SignedData;

public class CAUtil {

	/**
	 * CA文件签名
	 * 
	 * @author [lv tang wei] Describe:
	 * @param inFile
	 *            签名前文件
	 * @param outFile
	 *            签名后文件
	 * @param cert
	 *            证书
	 * @param pwd
	 *            证书密码
	 * @throws Exception
	 *             [2017年7月7日]
	 */
	public static void signFile(String inFile, String outFile,
			Certificate cert, String pwd) throws Exception {

		FileInputStream fIn = null;
		FileOutputStream fOut = null;
		byte[] in = new byte[8192];
		byte[] out;
		int len;
		SignedData sign = null;
		try {
			sign = new SignedData(true);
			sign.setDetached(false);
			sign.setSignCertificate(cert, pwd);// 设置签名证书和密码
			sign.setSignAlgorithm(0, Signature.SHA256WITHRSA);
			fIn = new FileInputStream(inFile);
			fOut = new FileOutputStream(outFile);
			out = sign.signInit();
			fOut.write(out);
			for (;;) {
				len = fIn.read(in);
				if (len <= 0) {
					break;
				}
				out = sign.signUpdate(in, 0, len);
				fOut.write(out);
			}
			out = sign.signFinal();
			fOut.write(out);
		} finally {
			if (fIn != null) {
				fIn.close();
			}
			if (fOut != null) {
				fOut.close();
			}
			if (sign != null) {
				sign.free();
			}
			if (cert != null) {
				cert.free();
				cert = null;
			}
		}
	}
	
	/**
	 * CA文件签名
	 * 
	 * @author [lv tang wei] Describe:
	 * @param inFile
	 *            签名前文件
	 * @param outFile
	 *            签名后文件
	 * @param cert
	 *            证书
	 * @param pwd
	 *            证书密码
	 * @throws Exception
	 *             [2017年7月7日]
	 */
	public static void verifySignFile(String inFile, String outFile,
			Certificate cert, String pwd) throws Exception {

		FileInputStream fIn = null;
		FileOutputStream fOut = null;
		byte[] in = new byte[8192];
		byte[] out;
		int len;
		SignedData sign = null;
		try {
			sign = new SignedData(false);
			sign.addCertificate(cert); //如果SignedData不带有证书，则需要 

			fIn = new FileInputStream(inFile);
			fOut = new FileOutputStream(outFile);
			sign.verifyInit();
			for (;;) {
				len = fIn.read(in);
				if (len <= 0) {
					break;
				}
				out = sign.verifyUpdate(in, 0, len);
				fOut.write(out);
			}
			sign.verifyFinal();
		} finally {
			if (fIn != null) {
				fIn.close();
			}
			if (fOut != null) {
				fOut.close();
			}
			if (sign != null) {
				sign.free();
			}
			if (cert != null) {
				cert.free();
				cert = null;
			}
		}
	}

	public static Certificate getLoginCert(String sn) throws PkiException {
		Certificate cert = null;
		try {
			DeviceSet set = NetcaPKI.getDeviceSet();
			for (int i = 0; i < set.count(); i++) {
				Device device = set.get(i);
				if (device.getSerialNumber().equals(sn)) {
					KeyPair KeyPair = device.getKeyPair(i);
					cert = KeyPair.getCertificate(i);
					// 有效期检查
					java.util.Date oDateEnd = cert.getValidityEnd();
					java.util.Date oDateBegin = cert.getValidityStart();
					java.util.Date oDateNow = new java.util.Date();
					if (oDateNow.compareTo(oDateBegin) < 0
							&& oDateNow.compareTo(oDateEnd) > 0) {// 找出有效期内证书
						break;
					}
					// CA标志检查
					String sCATitle = NetcaPKI.getX509CertificateInfo(cert,
							NetcaPKI.CATITLE);
					if (sCATitle == null || "".equals(sCATitle)) {
						break;
					}
					int iKeyUse = cert.getKeyUsage();
					int NETCAPKI_KEYUSAGE_DIGITALSIGNATURE = 1;
					int NETCAPKI_KEYUSAGE_NONREPUDIATION = 2;
					/* 检查是否是签名证书 */
					if (!((iKeyUse == (NETCAPKI_KEYUSAGE_DIGITALSIGNATURE | NETCAPKI_KEYUSAGE_NONREPUDIATION))
							|| (iKeyUse == -1) || (iKeyUse == NETCAPKI_KEYUSAGE_DIGITALSIGNATURE))) {
						break;
					}
				}
			}
		} catch (PkiException e) {
			e.printStackTrace();
			throw new PkiException(e.getMessage());
		}
		return cert;
	}
	
	public static void main(String args[]) {  
		   try {  
		       System.out.println(getMD5Checksum("D:\\dzbl\\pdf\\20150077\\1\\24小时出入院记录.pdf"));  
		   }  
		   catch (Exception e) {  
		       e.printStackTrace();  
		   }  
		}  
		  
		public static byte[] createChecksum(String filename) throws Exception {  
		   InputStream fis =  new FileInputStream(filename);          //<span style="color: rgb(51, 51, 51); font-family: arial; font-size: 13px; line-height: 20px;">将流类型字符串转换为String类型字符串</span>  
		  
		   byte[] buffer = new byte[1024];  
		   MessageDigest complete = MessageDigest.getInstance("MD5"); //如果想使用SHA-1或SHA-256，则传入SHA-1,SHA-256  
		   int numRead;  
		  
		   do {  
		       numRead = fis.read(buffer);    //从文件读到buffer，最多装满buffer  
		       if (numRead > 0) {  
		       complete.update(buffer, 0, numRead);  //用读到的字节进行MD5的计算，第二个参数是偏移量  
		       }  
		   } while (numRead != -1);  
		  
		   fis.close();  
		   return complete.digest();  
		}  
		  
		public static String getMD5Checksum(String filename) throws Exception {  
		   byte[] b = createChecksum(filename);  
		   String result = "";  
		  
		   for (int i=0; i < b.length; i++) {  
		       result += Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring(1);//加0x100是因为有的b[i]的十六进制只有1位  
		   }  
		   return result;  
		}  
}
